// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
 *    NAND Flash Controller V301 Device Driver
 *    Copyright (c) 2009-2010 by Hisilicon.
 *    All rights reserved.
 * ***
 *
 ******************************************************************************/

#ifndef HIFMCV100H
#define HIFMCV100H
#include "hibase.h"

#define CONFIG_RTOS_SETUP_NAND_MAX_CHIP

#ifndef CONFIG_FMC_MAX_CHIP
#ifdef CONFIG_RTOS_SETUP_NAND_MAX_CHIP
#define CONFIG_FMC_MAX_CHIP                   (2)
#else
#define CONFIG_FMC_MAX_CHIP                   (1)
#endif
/* warning NOT config CONFIG_FMC_MAX_CHIP, used default value, maybe invalid. */
#endif

#define FMC_REG_BASE_ADDRESS_LEN              (0x100)
#define FMC_BUFFER_BASE_ADDRESS_LEN           (2048 + 128)

#define FMC_CHIP_DELAY                        (25)
#define FMC_CHIP_RESET_DELAY                  (50)

#define FMC_ADDR_CYCLE_MASK                    0x4

#define FMC_CFG_PAGEISZE_SHIFT           (3)
#define FMC_CFG_BLOCKSZE_SHIFT           (8)

#define FMC_CFG_PAGESIZE_MASK            (0x03)
#define FMC_CON_BUS_WIDTH                (1U << 4)
#define FMC_GLOBAL_CFG_READY_BUSY_SEL    (1U << 8)
#define FMC_CFG_ECCTYPE_SHIFT            (5)
#define FMC_CFG_ECCTYPE_MASK             (0x07)
#define FMC_INT_MASK                     (0x0C)
#define FMC_INT                          (0x18)
#define FMC_INTCLR                        0x20

/*
 * when the software is doing delivery operate,the configuration is 1 and the
 * controller will automatically clear
 */
#define FMC_OP_CTRL_DMA_OP_READY         (1U << 0)
/* the type of operate of delivery:DMA write */
#define FMC_OP_CTRL_RW_OP                (1U << 1)

#define FMC_OP_CFG_CS_SHIFT              (11)
#define FMC_OP_CFG_CS_MASK               (0x01)
#define FMC_OP_CFG_ADDR_NUM_MASK         (0x07)
#define FMC_OP_CFG_ADDR_NUM_SHIFT        (4)
#define FMC_OP_CFG_IF_TYPE_MASK          (0x07)
#define FMC_OP_CFG_IF_TYPE_SHIFT         (7)
#define FMC_OP_CFG_DUMMY_NUM_MASK        (0x0f)

#define FMC_OP_CTRL_WR_OPCODE_MASK       (0xff)
#define FMC_OP_CTRL_WR_OPCODE_SHIFT      (8)
#define FMC_OP_CTRL_RD_OPCODE_MASK       (0xff)
#define FMC_OP_CTRL_RD_OPCODE_SHIFT      (16)

#define FMC_CMD_WRITE_ENABLE             (0x06)
#define FMC_CMD_GET_FEATURE              (0x0f)
#define FMC_CMD_SET_FEATURE              (0x1f)

#define SPI_NAND_BLOCK_PROTECTION_REGISTER  (0xa0)
#define SPI_NAND_SECURE_OTP_REGISTER        (0xb0)
#define SPI_NAND_STATUS_REGISTER            (0xc0)

#define FMC_DMA_LEN_OOB_MASK             (0xFFF)

#define FMC_MT29F1G_ADDR_PROGRAM_PAGE    0x80
#define FMC_MT29F1G_ADDR_PROGRAM         0x1c000000
#define FMC_MT29F1G_LOW_DRIVER_MODE      3

/* FMC status register to detect the maximum number of polls */
#define FMC_CHECK_STATUS_LOOP_MAX        10000000
/* Software can only be configured as 1, logic for enable */
#define FMC_OP_REG_OP_START              (1U << 0)
#define FMC_OP_READ_STATUS_EN            (1U << 1)  /* enable to read from FLash */
#define FMC_OP_READ_DATA_EN              (1U << 2)  /* enable to read from FLash */
/* nand flash needs to wait for signal of ready/busy up for enable */
#define FMC_OP_WAIT_READY_EN             (1U << 3)
#define FMC_OP_CMD2_EN                   (1U << 4)  /* Issue command2 to flash */
#define FMC_OP_WRITE_DATA_EN             (1U << 5)  /* write data for enable to FLash */
/* write operated address for enable to FLASH */
#define FMC_OP_ADDR_EN                   (1U << 6)
#define FMC_OP_CMD1_EN                   (1U << 7)  /* send command1 for enable to flash */
#define FMC_OP_DUMMY_EN                  (1U << 8)  /* Dump command to flash */

#define FMC_CFG                          0
#define PND_PWIDTH_CFG                   0xc
#define FMC_CMD                          0x24
#define FMC_OP                           0x3c
#define FMC_ADDRL                        0x2c
#define FMC_ADDRH                        0x28
#define FMC_OP_CFG                       0x30
#define FMC_FLASH_INFO                   0xac
#define FMC_DATA_NUM                     0x38
#define FMC_DMA_SADDR_D0                 0x4c
#define FMC_DMA_SADDR_OOB                0x5c
#define FMC_DMA_LEN                      0x40
#define FMC_OP_CTRL                      0x68
#define GLOBAL_CFG                       0x4

#define FMC_REG_BASE                     0x10a20000
#define FMC_MEM_BASE                     0x1c000000
#define FMC_READ_ID_SPI                  0x9f
#define FMC_READ_ID_NAND                 0x90
#define FMC_CMD_NAND_RESET               0xff

#define NAND_FLASH_TYPE                  1
#define SPI_NAND_FLASH_TYPE              2

#define FMC_512B                            (512)
#define FMC_2K                              (2048)
#define FMC_4K                              (4096)
#define FMC_8K                              (8192)
#define FMC_16K                             (16384)
#define FMC_32K                             (32768)

#define FLASH_TYPE_REG_NUM               8
#define FLASH_TYPE_5117P_REG_NUM         4
#define CONFIG_RTOS_STORAGE_FMC_8BIT_ECC 1

enum ecc_type {
	et_ecc_5117_none = 0x00,
	et_ecc_5117_8bit = 0x01,
	et_ecc_5117_16bit = 0x02,
	et_ecc_5117_24bit = 0x03,
	et_ecc_5117_28bit = 0x04,
	et_ecc_5117_40bit = 0x05,
	et_ecc_5117_64bit = 0x06,
};

enum page_fmc_type {
	pt_fmc_pagesize_2K = 0x00,
	pt_fmc_pagesize_4K = 0x01,
	pt_fmc_pagesize_8K = 0x02,
	pt_fmc_pagesize_16K = 0x03,
};

enum block_fmc_type {
	bt_blocksize_64 = 0x00,
	bt_blocksize_128 = 0x01,
	bt_blocksize_256 = 0x02,
	bt_blocksize_512 = 0x03,
};

struct fmc_page_ecc_info {
	enum page_fmc_type pagetype;
	unsigned int ecctype;
	unsigned int oobsize;
	//struct nand_ecclayout *layout;
	struct mtd_ooblayout_ops *layout;
};

struct fmc_block_status_info {
	unsigned int *flash_block_erase_time;
	unsigned int block_size;
	unsigned int block_index;
	unsigned int page_per_block;
	unsigned int valid;
};

extern char g_flash_cmd_line[];
extern unsigned long g_default_oob_size;

extern void (*nand_base_oob_resize)(struct mtd_info *mtd, struct nand_chip *chip);

int fmc_nand_init(struct hinfc_host *host, struct nand_chip *chip);
int hifmc_chip_reset_test(struct hinfc_host *host);
int fmc_flash_feature_init(struct mtd_info *mtd);
#endif
